HTML5 API includes Drag and Drop (DnD) native functionality.
The event listener methods for all the drag and drop events accept Event object which has a readonly attribute called dataTransfer. The event.dataTransfer returns DataTransfer object associated with the event
This is the list of events fired during the different stages:
| Event | Description |
|---|---|
| dragstart | Fires when the user starts dragging of the object. |
| dragenter | Fired when the mouse is first moved over the target element while a drag is occuring. A listener for this event should indicate whether a drop is allowed over this location. If there are no listeners, or the listeners perform no operations, then a drop is not allowed by default. |
| dragover | This event is fired as the mouse is moved over an element when a drag is occuring. Much of the time, the operation that occurs during a listener will be the same as the dragenter event. |
| dragleave | This event is fired when the mouse leaves an element while a drag is occuring. Listeners should remove any highlighting or insertion markers used for drop feedback. |
| drag | Fires every time the mouse is moved while the object is being dragged. |
| drop | The drop event is fired on the element where the drop was occured at the end of the drag operation. A listener would be responsible for retrieving the data being dragged and inserting it at the drop location. |
| dragend | Fires when the user releases the mouse button while dragging an object. |
In this post we develop an application to handle the drag and drop events between two elements, and launch a HttpPost method in the server which will ends inserting the dragged value in database.
First of all we create an MVC project in C#. Under Controller folder in the HomeController we add this code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace HTML5DragAndDrop.Controllers {
public class HomeController : Controller {
ITestDatabase _testDatabase = new TestDatabase();
public ActionResult Index() {
return View();
}
public ActionResult About() {
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact() {
ViewBag.Message = "Your contact page.";
return View();
}
[HttpPost]
public JsonResult InsertTestElements(string testElement) {
int? insertResult = null;
if (!string.IsNullOrEmpty(testElement)) {
string[] elementData = testElement.Split(':');
string symbol = elementData[0].Trim();
string name = elementData[1].Trim();
insertResult = _testDatabase.InsertElement(symbol, name);
}
return Json(insertResult);
}
}
}
Now we create a folder in the root of the project called Code. Under this folder we create two new files:
ITestDatabase.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public interface ITestDatabase {
int InsertElement(string symbol, string name);
}
TestDatabase.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public class TestDatabase : ITestDatabase {
/// <summary>
/// Save an element in the database and return the new ID
/// </summary>
/// <param name="symbol"></param>
/// <param name="name"></param>
/// <returns></returns>
public int InsertElement(string symbol, string name) {
// save the element in database
// now it returns just a number: it will be the Id of the record
return 1;
}
}
The first step is the definition of the UXinterface, in sequence the display is this
We are adding h5utils.js file, with an implementation of AddEvent function to simplify our code:
h5utils.js
var AddEvent = (function () {
if (document.addEventListener) {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.addEventListener(type, fn, false);
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
AddEvent(el[i], type, fn);
}
}
};
} else {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.attachEvent('on' + type, function ()
{
return fn.call(el, window.event);
});
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
AddEvent(el[i], type, fn);
}
}
};
}
})();
var pDragElement = document.createElement('p');
var chemicalElements = document.querySelectorAll('div > p'), el = null;
for (var i = 0; i < chemicalElements.length; i++) {
el = chemicalElements[i];
el.setAttribute('draggable', 'true');
AddEvent(el, 'dragstart', dragStartElement);
AddEvent(el, 'dragend', dragEndElement);
}
function dragStartElement(e) {
e.dataTransfer.effectAllowed = 'copy';
e.dataTransfer.setData('Text', this.id);
e.dataTransfer.setData('Type', this.innerHTML);
this.style.backgroundColor = "#ffa31a";
}
function dragEndElement(e) {
this.style.backgroundColor = "#fff9f0";
}
var divBoxElements = document.querySelector('#divBoxElements');
AddEvent(divBoxElements, 'dragover', function (e) {
if (e.preventDefault) e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
return false;
});
AddEvent(divBoxElements, 'drop', function (e) {
if (e.stopPropagation) e.stopPropagation();
var element = e.dataTransfer.getData('Type');
pDragElement.innerHTML = "Adding " + element + " element";
var pClone = pDragElement.cloneNode(true);
var newDiv = document.createElement("div");
newDiv.appendChild(pClone);
divBoxElements.appendChild(newDiv);
InsertTestElement(element);
return false;
});
In the Index.cshtml we change as following code:
Index.cshtml
@{
ViewBag.Title = "Home Page";
}
<div class="jumbotron">
<h1>Drag and drop example</h1>
<p class="lead">HTML5 API includes Drag and Drop (DnD)
native functionality. The event listener methods for all the drag and
drop events accept Event object which has a readonly attribute called
dataTransfer. The event.dataTransfer returns DataTransfer object
associated with the event.</p>
<p><a href="https://puresourcecode.com"
class="btn btn-primary btn-lg">Learn more »</a></p>
</div>
<div class="row">
<p id="1A">1: A</p>
<p id="2B">2: B</p>
<p id="3C">3: C</p>
<p id="4D">4: D</p>
<p id="5E">5: E</p>
<div id="divBoxElements
style="border: 1px solid #dcdcdc; width: 300px; height: 300px;"
></div>
</div>
@section scripts {
<script src="~/Scripts/html5utils.js"></script>
<script>
<!--
function InsertTestElement(element) {
var url = '@Url.Action("InsertTestElements", "Home")';
$.post(url, { testElement: element }, function (data) {
switch (data) {
case 1:
divBoxElements.innerHTML =
element + " inserted OK";
setTimeout(function () {
divBoxElements.innerHTML = ""; }, 2000);
break;
default:
alert("Error inserting the element");
}
});
}
//-->
</script>
}
Download or fork tthis code on Github.
Happy coding!
… [Trackback]
[…] Read More here: puresourcecode.com/dotnet/post/2016/03/28/c-and-html5-drag-and-drop-elements/trackback/ […]